package main.firefox;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.*;

import org.dbrd.preprocessor.xml.MozillaXMLReportPreprocessor;
import org.sun.dbrd.IdsPreprocessor.VersionOrderMap;
import org.sun.dbrd.mains.AbstractPreprocessorMain;

public class StartDrifting extends AbstractPreprocessorMain {

	public static String projectName = "OpenOffice";
	public static String esIndexName = "openoffice5";
	public static int iteration = 100;
	public static int progress = 0;

	public static int year = 0;

	// 需要在代码中设置好缺陷报告的位置
	public static String directory = "../../Studied_ITS_Data/" + projectName + "_XMLs/" + "bugs";
	// 需要在代码中设置好使用的IR方法
	public static boolean BM25Fext = false;

	public static String saveDirectory = "./ExtendBackward/" + projectName;
	public static long startingId;
	public long trainingTarget = 0;

	public int threadNum = 10;
	// public static String ResultsDic =
	// "./../../../../scratch1/samy/Eclipse/ExtendBackward2008_40";

	public static String ResultsDic = "./ExtendBackward" + "/"
			+ projectName + "/RandomPreviousResearch100";

	public static String Origin100ChunksClassicalResultsDic = "../100chunks_Classical/OpenOffice结果/OpenOfficeResults/RandomPreviousResearch100Simple";

	public static boolean fixedWindow = true;
	public static Map<String, String> startHashMap = new HashMap<String, String>();
	public static TreeMap<Integer, SortObj> sortingMap;

	public static long topN = 1000;

	public static TreeMap<String, Integer> trainingSizeMap = new TreeMap<String, Integer>();

	public int currentYear;

	public int currentMonth;

	public StartDrifting() {

	}

	public StartDrifting(int month, int year, long trainingTarget) {
		this.currentMonth = month;
		this.currentYear = year;
		this.trainingTarget = trainingTarget;

	}

	public static void main(String[] args) {

		new StartDrifting().mainDo();
	}

	public void mainDo() {
		// TODO Auto-generated method stub

		// Drifting
		// Eclipse from 82056 to 300000 (From 2005 to 2011)
		// Mozilla from 327493 to 587329 (From 2006 t o 2011)
		int tempYear;
		int tempMonth;
		if (projectName.equals("Mozilla")) {
			year = 2010;
		} else if (projectName.equals("Eclipse")) {

			year = 2008;
		} else if (projectName.equals("OpenOffice")) {
			year = 2008;
		}
		int[] yearsOfStudy = { year };
		int trainingSizeTemp = 0;

		
		// 操他妈的，作者傻逼吧，没用的代码你他妈写上，这个他妈的MotiviationrandomLimit.DATA需要用ExploratoryStudy_Classical_Recall来解析
		// 本程序生成的结果才能得到
		
//		try {
//			ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
//					"./../../../../scratch1/samy/" + projectName + "/"
//							+ projectName + "_" + 5 + "MotiviationrandomLimit.DATA"));
//			startHashMap = (Map) ois.readObject();
//		} catch (Throwable rt) {
//			rt.printStackTrace();
//			System.out.println();
//			System.exit(0);
//		}
//
		System.err
				.println(projectName
						+ "  "
						+ year
						+ "  --> Started Motiviation reading CSV. 80 file of years: Random Previous Work");

		System.err.println("Started Motiviation reading CSV file of years");

        // 文件里存储着每一年，每个月的报告id划分
        DataRange_Reader dataRange_Reader = new DataRange_Reader("../../Studied_ITS_Data/" + projectName + "_issues_extra_info/"
                + projectName + "Drift.csv");

        // 文件里存储着按时间（bug_id大小）顺序排序的报告信息（主要是bug_id，和时间信息）
        SortReaderObj Sort_Reader = new SortReaderObj("../../Studied_ITS_Data/" + projectName + "_issues_extra_info/" + projectName
                + "Time.csv");
		sortingMap = Sort_Reader.getMapResults();

		int minId = sortingMap.firstKey();
		int maxId = sortingMap.lastKey();

		System.out.println("First ID== " + minId + " , LastId== " + maxId);

		TreeMap<Integer, TreeMap<Integer, DataRange>> rangesTree = dataRange_Reader
				.getMapResults();
		trainingSizeMap.clear();

		int duplicatesIdWindow = 0;

		ExecutorService prepareThreadsPool = Executors
				.newFixedThreadPool(threadNum);

		System.err.println("Random Motiviation  Previous Work ~ Working on year : "
				+ currentYear);

		Random rand = new Random();

		int i = 0;

		trainingSizeTemp = 0;
		int randMaxID = 0;
		// Same evaluated periods are set here.
//		for (i = 0; i < iteration; i = i + 1) {
//			int randMinId = -1;
//
//			// 因为是Exploratory部分的实验，Evaluation Period都是确定的，所以
//			// 三个项目全都直接给出了randMinId和randMaxID的值，卡住了Evaluation Period的范围
//			if (projectName.equals("Mozilla")) {
//				year = 2010;
//				randMinId = 537438;
//
//				randMaxID = 622319;
//
//			} else if (projectName.equals("Eclipse")) {
//
//				year = 2008;
//				randMinId = 214049;
//				randMaxID = 259845;
//
//			} else if (projectName.equals("OpenOffice")) {
//				randMinId = 84927;
//				randMaxID = 116272;
//			}
//
//			System.out.println("Starting Drifting");
//			tempYear = currentYear;
//			tempMonth = currentMonth;
//			System.err.println("i= " + i
//					+ "Random  Previous Work Working on  startID: " + randMinId
//					+ " , endID:" + randMaxID);
//
//			trainingTarget = i;
//
//
//			DataPrepareThread dataPrepareThread = new DataPrepareThread(null,
//					currentMonth, currentYear, trainingTarget, randMinId,
//					randMaxID);
//			prepareThreadsPool.execute(dataPrepareThread);
//
//		}

		/**
		 * 2021-3-1 shangchao 读取原来的100ChunksClassical生成的100个随机时间段的数据集，
		 * 以它们的id范围来生成带语义向量的reports-large.txt文件
		 */
		File folder = new File(Origin100ChunksClassicalResultsDic);
		File[] listOfFiles = folder.listFiles();
		System.out.println("Size of " + listOfFiles.length);
		for (i = 0; i < listOfFiles.length; i = i + 1) {
			int randMinId = -1;
			File currentFile = listOfFiles[i];
			String nameStr = currentFile.getName();
			String[] splits = nameStr.split("_");

			randMaxID = Integer.parseInt(splits[2]);

			randMinId = Integer.parseInt(splits[1]);

			System.out.println(i + " ->Starting Drifting");
			tempYear = currentYear;
			tempMonth = currentMonth;

			trainingTarget = Integer.parseInt(splits[0]);


			System.out.println("Starting Drifting");
			tempYear = currentYear;
			tempMonth = currentMonth;
			System.err.println("i= " + i
					+ "Random  Previous Work Working on  startID: " + randMinId
					+ " , endID:" + randMaxID);

			trainingTarget = i;

			DataPrepareThread dataPrepareThread = new DataPrepareThread(null,
					currentMonth, currentYear, trainingTarget, randMinId,
					randMaxID);
			prepareThreadsPool.execute(dataPrepareThread);
		}

		prepareThreadsPool.shutdown();
		while (!prepareThreadsPool.isTerminated()) {
			try {
				Thread.sleep(9000L);
			} catch (Throwable throwable) {

			}
		}
		System.err.println("Finished all prepare Threads");

		System.err.println("Finished all threads");

	}




	public static DataRange getPreviousMonthRange(Integer year, Integer Month,
			TreeMap<Integer, TreeMap<Integer, DataRange>> rangesTree) {

		if (Month == 1) {
			Month = 12;
			year--;

		} else {
			Month--;
		}

		return rangesTree.get(year).get(Month);
	}

	@Override
	protected File getMappingFile() {
		return new File(saveDirectory + "/id-" + trainingTarget + "_"
				+ currentMonth + "_" + currentYear + "_"
				+ "-reports.txt-mapping.txt");
	}

	@Override
	protected File getResultFile() {
		return new File(saveDirectory + "/id-" + trainingTarget + "_"
				+ currentMonth + "_" + currentYear + "_" + "-reports-large.txt");
	}

	@Override
	protected File getSummaryFile() {
		return new File(saveDirectory + "/" + trainingTarget + "_"
				+ currentMonth + "_" + currentYear + "_" + "-reports.txt");
	}

	@Override
	protected VersionOrderMap createVersionOrderMap(File versionOrderFile) {
		return new VersionOrderMap(versionOrderFile) {
			@Override
			public int getVersionOrder(String version, int reportId) {
				return 1;
			}

			@Override
			protected void initialize(File versionOrderFile) {
			}
		};
	}

	@Override
	protected File getVersionOrderFile() {
		return null;
	}

	public int getIDBeforeOneYear(int ID) {

		int tempID = ID;
		boolean gotOneYear = true;

		SortObj randomSortObj = sortingMap.get(ID);

		while (gotOneYear && randomSortObj != null && tempID >= 0) {
			tempID--;
			SortObj sortOb = sortingMap.get(tempID);

			// System.out.println(tempID);
			if (sortOb != null) {

				long startTime = randomSortObj.getDate().getTime();
				long endTime = sortOb.getDate().getTime();
				long diffTime = startTime - endTime;
				long diffDays = diffTime / (1000 * 60 * 60 * 24);
				if (diffDays > 365) {

					if (tempID == 70230 || tempID == 70229 || tempID < 300
							|| tempID == 109043) {
						continue;
					}
					gotOneYear = false;
				}
			} else {
				System.err.println("SortObj not found for " + tempID);
			}

			if (sortingMap.firstEntry().equals(tempID) && gotOneYear) {
				tempID = -1;
				gotOneYear = false;

			}

		}

		return tempID;

	}

}

/*
 * class CommandThread extends Thread { private String currentCommand;
 * 
 * public CommandThread(String command) { currentCommand = command; }
 * 
 * @Override public void run() { // TODO Auto-generated method stub
 * executeCommand(currentCommand); }
 * 
 * public String executeCommand(String command) {
 * 
 * StringBuffer output = new StringBuffer();
 * 
 * Process p; try { p = Runtime.getRuntime().exec(command); p.waitFor(); //
 * BufferedReader dd=new BufferedReader(new //
 * InputStreamReader(p.getInputStream())); BufferedReader reader = new
 * BufferedReader(new InputStreamReader( p.getInputStream()));
 * 
 * // InputStreamReader streamReader= new //
 * InputStreamReader(p.getInputStream()); String line = ""; while ((line =
 * reader.readLine()) != null) { System.out.println(line + "\n"); }
 * 
 * System.err.println("Done with Command : " + command);
 * 
 * } catch (Exception e) { e.printStackTrace(); }
 * 
 * return output.toString();
 * 
 * }
 * 
 * }
 */

class DataPrepareThread extends Thread {
	private DataRange tempDataRange;

	private long trainingTarget;

	public int startID;
	public int endId;

	public DataPrepareThread(DataRange range, int month, int year,
			long trainingTarget, int StartId, int endId) {
		this.tempDataRange = new DataRange();
		// tempDataRange.setMaxLimit(range.getMaxLimit());
		// tempDataRange.setMinLimit(range.getMinLimit());
		// tempDataRange.setMonth(range.getMonth());
		// tempDataRange.setYear(range.getYear());
		// tempDataRange.setNumberOfReports(range.getNumberOfReports());

		// this.currentMonth = month;
		// this.currentYear = year;
		this.trainingTarget = trainingTarget;
		this.startID = StartId;
		this.endId = endId;

	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		executeCommand();
	}

	public void executeCommand() {

		System.err
				.println(" Random gen direction Inside dataprepare thread for : "
						+ " "
						+ trainingTarget
						+ "_"
						+ startID
						+ "_"
						+ endId
						+ "  reports "
						+ " TempYear="
						+ tempDataRange.getYear()
						+ " , TeamMonth=" + tempDataRange.getMonth());

		int trainingSizeTemp;

		trainingSizeTemp = new MozillaXMLReportPreprocessor(
				new File(StartDrifting.saveDirectory, trainingTarget + "_" + startID
						+ "_" + endId + "_" + "-reports.txt"),
				new File(StartDrifting.directory), (startID), endId)
				.process(startID, startID, StartDrifting.fixedWindow);

		System.err.println(" Random gen direction done  processing data.... "
				+ " " + trainingTarget + "_" + startID + "_" + endId
				+ "  reports " + " TempYear=" + tempDataRange.getYear()
				+ " , TeamMonth=" + tempDataRange.getMonth());

		File f = new File(StartDrifting.ResultsDic + "/" + trainingTarget + "_"
				+ startID + "_" + endId + "_" + trainingSizeTemp + "_"
				+ startID + "_" + endId + "_" + "Results");
		if (f.exists()) {
			System.err.println("Already exists :  " + StartDrifting.ResultsDic
					+ "/" + trainingTarget + "_" + startID + "_" + endId + "_"
					+ trainingSizeTemp + "_" + startID + "_" + endId + "_"
					+ "Results");
			return;
		}

		// Add the training Size to the map
		StartDrifting.trainingSizeMap.put(trainingTarget + "_" + startID + "_"
				+ endId, trainingSizeTemp);

		System.err.println("Using training Duplicates : " + trainingSizeTemp
				+ " for " + trainingTarget + "_" + startID + "_" + endId
				+ "  reports ");

		System.out.println("Processing Ids...");

		// 这个run运行的是父类AbstractPreprocessorMain的run
		/**
		 * @see AbstractPreprocessorMain#run()
		 */
		new StartDrifting(startID, endId, trainingTarget).run();

		System.out.println("Running Detection ... for +" + trainingSizeTemp
				+ " for " + trainingTarget + "_" + startID + "_" + endId
				+ "  reports ");

		// Get the training size of this chunk

		/*
		 * trainingSizeTemp = trainingSizeMap.get(trainingTarget + "_" +
		 * currentMonth + "_" + currentYear);
		 */
		String type = "";
		if (StartDrifting.BM25Fext) {
			type = "/with-query-no-categorial.cfg ";
		} else {

			type = "/full-textual-full-categorial.cfg ";


		}

		String command = StartDrifting.saveDirectory + "/dbrd.v2 -k "
				+ (StartDrifting.topN) + " --training-duplicates "
				+ trainingSizeTemp + "  -i 1 -n  "
				+ trainingTarget + "Titles --recommend  "
				+ StartDrifting.ResultsDic + "/" + trainingTarget + "_"
				+ startID + "_" + endId + "_" + trainingSizeTemp + "_"
				+ startID + "_" + endId + "_" + "Results -r "
				+ StartDrifting.saveDirectory + type
				+ StartDrifting.saveDirectory + "/id-" + trainingTarget + "_"
				+ startID + "_" + endId + "_" + "-reports-large.txt";
		System.err.println("Running Command :" + command);
		executeCommand(command);

		System.gc();

		// scnb加的：只保留reports-large.txt等文件也删掉，留出足够的剩余空间
//		deleteFile(StartDrifting.saveDirectory + "/id-" + trainingTarget + "_"
//				+ startID + "_" + endId + "_" + "-reports-large.txt");

		deleteFile(StartDrifting.saveDirectory + "/id-" + trainingTarget + "_"
				+ startID + "_" + endId + "_" + "-reports.txt-mapping.txt");

		deleteFile(StartDrifting.saveDirectory + "/" + trainingTarget + "_"
				+ startID + "_" + endId + "_" + "-reports.txt");

		StartDrifting.progress++;
		System.err.println("Total Done is " + StartDrifting.progress
				+ " , Percentage: % " + ((double) StartDrifting.progress)
				/ ((double) StartDrifting.iteration / 2.0d));

	}

	public String executeCommand(String command) {

		StringBuffer output = new StringBuffer();

		Process p;
		try {
			p = Runtime.getRuntime().exec(command);
			p.waitFor();
			// BufferedReader dd=new BufferedReader(new
			// InputStreamReader(p.getInputStream()));
			BufferedReader reader = new BufferedReader(new InputStreamReader(
					p.getInputStream()));

			// InputStreamReader streamReader= new
			// InputStreamReader(p.getInputStream());
			String line = "";
			while ((line = reader.readLine()) != null) {
				System.out.println(line + "\n");
			}

			System.err.println("Done with Command : " + command);

		} catch (Exception e) {
			e.printStackTrace();
		}

		return output.toString();

	}

	public void deleteFile(String fileName) {

		File f = null;
		boolean bool = false;

		try {
			// create new file
			f = new File(fileName);

			// tries to delete a non-existing file
			bool = f.delete();

			// prints
			System.out.println("File deleted: " + bool);

			// creates file in the system
			f.createNewFile();

			// createNewFile() is invoked
			System.out.println("createNewFile() method is invoked");

			// tries to delete the newly created file
			bool = f.delete();

			// print
			System.out.println("File deleted: " + bool);

		} catch (Exception e) {
			// if any error occurs
			// e.printStackTrace();
		}
	}

}